import { messages } from "share/common";
import React, { Component, PropTypes } from 'react';
import { Icon, Form, Button, Tooltip, Row, Col } from 'antd';
import Condition from 'components/condition'
import 'styles/components/advanced-search/advanced-search.scss'
const { If } = Condition;
import { formatValue } from './utils'
import AdvancedSearchTagList from './advanced-search-tag-list'
import AdvancedSearchFormItem from './advanced-search-form-item'
import AdvancedSearchPinnedList from './advanced-search-pinned-list'
import AdvancedSearchTitle from './advanced-search-title'

/**
 * 2019-8-1 Wrote by ZaraNengap:
 * 高级搜索，第一次中控风格更改和重构SearchArea的产物
 * SearchArea越来越大而且难以维护，写组件时还是没有想到一些业务场景
 * 此组件在SearchArea的基础上大大提高了灵活性，实现了万物皆可注入
 * 很多不必要的逻辑都封装到对应组件和外部了，这个组件看起来很清爽
 * 经过这个组件我逐渐发现一个组件把能做的不能做的都做了并不是一件好事
 * 新的web组件思想是状态自治，所以很多不属于"提供一个搜索区域并渲染表单组件"的逻辑这次都没有放进来
 * 比如SearchArea里对Select、Radio等组件的数据处理，完全应该应用状态自治的思想封装到外部
 * 这个组件只负责展示区域和数据，组件内部的数据不应该我们来做
 * （除了Selector和Chooser、Searcher当初糟糕的entity参数和onlyNeed参数，这两个的数据处理本来也不属于这里）
 * 希望读到这个注释的developer在之后的维护当中也能考虑一下最小状态的组件思想
 * 这样这个组件就不会称为下一个SearchArea
 *
 * 2019-8-6 Wrote by ZaraNengap
 * 本来这个文件夹下的所有代码都在这一个文件里
 * 但是当我开始写AdvancedTable时，发现很多可以复用的逻辑，所以不得不又做了一次拆分
 * 也许一开始就应该秉承状态自治的思想，直接一步拆好，不用做额外的工作
 */
class AdvancedSearch extends Component {

  state = {
    collapsed: false,
    filterTags: [],
    controlledStyle: {},
    showForm: true
  };

  filterTagListRef = null;

  componentDidMount() {
    const { form, getForm, onRef } = this.props;
    getForm && getForm(form);
    onRef && onRef(this);
  }

  getFormField = field => {
    const { form } = this.props;
    return <AdvancedSearchFormItem
      form={form}
      field={field}
    />
  };

  setFilterTags = (values, searchForm, onSet) => {
    this.setState({ filterTags: AdvancedSearchTagList.getFilterTags(values, searchForm) }, () => {
      onSet && onSet();
      this.filterTagListRef && this.filterTagListRef.resetList();
    });
  };

  search = noTrigger => {
    const { form, onSearch, searchForm } = this.props;
    return new Promise(resolve => {
      form.validateFields((error, values) => {
        if(!error) {
          this.setFilterTags(values, searchForm, () => {
            let target = formatValue(values, searchForm);
            if(noTrigger === true) {
              resolve([target, values]);
            } else {
              onSearch && onSearch(target, values);
            }
          });
        }
      });
    });
  };

  reset = needSearch => {
    const { form, onReset } = this.props;
    form.resetFields();
    this.setState({ filterTags: [] });
    onReset && onReset();
    needSearch && this.search();
  };

  onCloseTag = tag => {
    const { form } = this.props;
    const { filterTags } = this.state;
    this.setState({ filterTags: filterTags.filter(item => item.id !== tag.id) }, () => {
      form.setFieldsValue({ [tag.id]: null });
      this.search();
    });
  };

  renderButtonByConfig = (config, source) => {
    if(typeof config === 'string') {
      return <Button {...source}>{config}</Button>
    } else {
      return <Button {...Object.assign({}, source, config.props)}>{config.text}</Button>
    }
  };

  renderButtons = () => {
    const { searchButton, resetButton } = this.props;
    return <If value={searchButton || resetButton}>
      {this.renderButtonByConfig(
        searchButton,
        { onClick: this.search, type: 'primary', key: 'search' }
      )
      }
      {this.renderButtonByConfig(
        resetButton,
        { onClick: () => this.reset(true), key: 'reset' }
      )
      }
    </If>
  };

  onChangeCondition = value => {
    const { form } = this.props;
    form.setFieldsValue(value);
    this.search();
  };

  render() {
    const { collapsed, filterTags, showForm } = this.state;
    const {
      title, showFilterTags, renderCollapseText, searchForm,
      onChangePinnedList, pinnedList, onCollapse, form, tableName
    } = this.props;
    return (
      <div className='advanced-search'>
        <div className='advanced-search-head'>
          <AdvancedSearchTitle
            pinnedList={pinnedList}
            title={title}
            searchForm={searchForm}
            onChangeCondition={this.onChangeCondition}
            onSearchParent={this.search}
            parentForm={form}
            tableName={tableName}
          />
          <span className='advanced-search-head-form'>
            <If value={searchForm.length > 0}>
            <Tooltip title={<span>
              {showForm ?
                messages('components.key1033')/*隐藏搜索条件*/ :
                messages('components.key1034')/*显示搜索条件*/
              }
            </span>} placement='top'>
              <Icon
                type='search'
                className={this.classNames(['advanced-search-head-form-show', { activated: showForm }])}
                onClick={this.toState({ showForm: !showForm }, onCollapse)}
              />
            </Tooltip>
            <span style={{ display: showForm ? 'inline' : 'none' }}>
              <span
                className='advanced-search-head-form-collapse'
                onClick={this.toState({ collapsed: !collapsed }, () => onCollapse(!collapsed))}
              >
                {renderCollapseText(searchForm.length - pinnedList.length, collapsed)}
              </span>
              <AdvancedSearchPinnedList
                searchForm={searchForm}
                pinnedList={pinnedList}
                onChange={onChangePinnedList}
                tableName={tableName}
              />
            </span>
          </If>
          </span>
        </div>
        <div
          className='advanced-search-pinned-form'
          style={{ display: showForm && (pinnedList.length > 0 || collapsed) ? 'block' : 'none' }}
        >
          <Row gutter={20}>
            {searchForm.map(field => (
              <Col
                span={field.row ? 24 : 6}
                style={{ display: pinnedList.has(field.id) || collapsed ? 'block' : 'none' }}
              >
                {this.getFormField(field)}
              </Col>
            ))}
          </Row>
          <div className='advanced-search-pinned-form-buttons'>
            {this.renderButtons()}
          </div>
        </div>
        <If value={showFilterTags}>
          <AdvancedSearchTagList
            onRef={filterTagListRef => this.filterTagListRef = filterTagListRef}
            filterTags={filterTags}
            onSearch={this.search}
            onReset={() => this.reset(true)}
            onCloseTag={this.onCloseTag}
          />
        </If>
      </div>
    )
  }

  static propTypes = {
    title: PropTypes.any,
    searchForm: PropTypes.array,  //表单配置项，具体可见advanced-search-doc.js
    onSearch: PropTypes.func,
    onReset: PropTypes.func,
    showFilterTags: PropTypes.bool,  //是否显示筛选标签列表
    renderCollapseText: PropTypes.any,
    popoverTitle: PropTypes.any,
    searchButton: PropTypes.oneOfType([PropTypes.bool, PropTypes.object, PropTypes.string]),
    resetButton: PropTypes.oneOfType([PropTypes.bool, PropTypes.object, PropTypes.string]),
    pinnedList: PropTypes.array,
    onChangePinnedList: PropTypes.func,
    tableName: PropTypes.string
  };

  static defaultProps = {
    searchForm: [],
    showFilterTags: true,
    renderCollapseText: (number, collapsed) => <span>
      {collapsed ?
        messages('components.key1035')/*收起多余条件*/ :
        messages('components.key1036')/*展开所有条件*/
      }
      ({number})
    </span>,
    popoverTitle: messages('components.key1037')/*高级搜索*/,
    searchButton: {
      props: { type: 'primary' },
      text: messages('common.search')/*搜索*/
    },
    resetButton: messages('common.reset')/*重置*/,
    onCollapse: () => {},
    pinnedList: [],
    onChangePinnedList: () => {}
  };

  //以下两个方法是为了应对一些级联事件的工具函数，在外部做时间判断的时候可用来操作searchForm数组

  static getFormById = (id, searchForm) => {
    return searchForm.find(formItem => formItem.id === id);
  };

  static setFormByItem = (item, searchForm) => {
    return searchForm.map(formItem => formItem.id === item.id ? item : formItem);
  };

}

export default Form.create()(AdvancedSearch);
